using UnityEngine;
using System.Collections;

public class CRSpline : MonoBehaviour
{
	ArrayList vp;

	float delta_t;

	bool dragging;

	int dragCount;

	Vector3 previousDrag;

	Vector3[] vertices;
	int num_verts;

	LineRenderer line;
	

	void Start()
	{ 
		vp = new ArrayList();
		dragging = false;
		vertices = new Vector3[202];
		num_verts = 0;
	} 

	void Update()
	{    
		Vector3 pos = Input.mousePosition;
		Vector3 p = Camera.main.ScreenToWorldPoint(new Vector3(pos.x, pos.y, pos.z));

		if (Input.GetMouseButtonDown(0))
		{
			OnTouchBegin(p);
		}
		else if (Input.GetMouseButton(0))
		{
			OnTouchMove(p);
		}
		else if (Input.GetMouseButtonUp(0))
		{
			OnTouchEnd(p);
		}
	} 

	void OnTouchBegin(Vector3 p)
	{
		dragCount = 0;
		//Clear();
		AddSplinePoint(p);
		dragging = true;
	}
	
	void OnTouchMove(Vector3 p)
	{
		if (dragging)
		{
			AddSplinePoint(p);
			if (dragCount < 50)
			{
				if (Vector3.Distance(p, previousDrag) >= 7)
				{
					AddSplinePoint(p);
					dragCount++;
					previousDrag = p;
				}
			}
		}
	}
	
	void OnTouchEnd(Vector3 p)
	{
		StopDraw();
		dragging = false;
	}
	

	// Solve the Catmull-Rom parametric equation for a given time(t) and vector quadruple (p1,p2,p3,p4)
	Vector3 Eq(float t, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4)
	{
		float t2 = t * t;
		float t3 = t2 * t;

		float b1 = 0.5f * (-t3 +  2 * t2 - t);
		float b2 = 0.5f * (  3 * t3 - 5 * t2 + 2);
		float b3 = 0.5f * ( -3 * t3 + 4 * t2 + t);
		float b4 = 0.5f * (t3 - t2);

		return (p1 * b1 + p2 * b2 + p3 * b3 + p4 * b4);
	}

	void AddSplinePoint(Vector3 v)
	{
		vp.Add(v);
		delta_t = 1.0f / vp.Count;
	}

	int BOUNDS(int p)
	{
		int pp = p;
		if (p < 0) pp = 0;
		else if (p >= vp.Count - 1) pp = vp.Count - 1;
		return pp;
	}
	
	Vector3 GetInterpolatedSplinePoint(float t)
	{
		// Find out in which interval we are on the spline
		int p = (int)(t / delta_t);
		// Compute local control point indices

		int p0 = p - 1;
		p0 = BOUNDS(p0);
		int p1 = p;
		p1 = BOUNDS(p1);
		int p2 = p + 1;
		p2 = BOUNDS(p2);
		int p3 = p + 2;
		p3 = BOUNDS(p3);
		// Relative (local) time
		float lt = (t - delta_t * (float)p) / delta_t;
		// Interpolate
		return Eq(lt, (Vector3)vp[p0], (Vector3)vp[p1], (Vector3)vp[p2], (Vector3)vp[p3]);
	}

	public int GetNumPoints()
	{
		return vp.Count;
	}

	public Vector3 GetNthPoint(int n)
	{
		return (Vector3)vp[n];
	}

	public void SetNthPoint(int n, Vector3 v)
	{
		vp[n] = v;
	}
	
	void RemoveFirst()
	{
		vp.RemoveAt(0);
	}

	public void Clear()
	{
		vp.Clear();
		num_verts = 0;
	}

	void StopDraw()
	{
		// Calc the full curve
		num_verts = 0;

		if (GetNumPoints() > 3)
		{
			for (float t = 0; t < 1.0f; t += 1.0f/25.0f)
			{
				Vector3 a = GetInterpolatedSplinePoint(t);
				vertices[num_verts].x = a.x;
				vertices[num_verts].y = a.y;
				vertices[num_verts].z = 0;
				num_verts++;
				
			}
			
			line = GetComponent(typeof(LineRenderer)) as LineRenderer;
			line.SetWidth(0.1f, 0.1f);
		
			line.SetVertexCount(num_verts);
			for (int i = 0; i < num_verts; i++)
			{
				line.SetPosition(i, vertices[i]);
			}
		}
	}
}
